package com.example.drainage.ui.shadow

import android.view.View
import android.view.ViewGroup
import androidx.core.view.ViewCompat

/**
 * @author 创建人 ：yanghaozhang
 * @version 1.0
 * @package 包名 ：com.example.drainage.ui.shadow
 * @createTime 创建时间 ：2021/11/27
 * @modifyBy 修改人 ：
 * @modifyTime 修改时间 ：
 * @modifyMemo 修改备注：
 */

/**
 * 1指定阴影模糊半径,设置shadowAffectRadius,shadowDx,shadowDy,此时没有设置shadowMargin的一侧,自动计算阴影需要的绘制区间
 * 2指定阴影显示的空间大小,设置shadowMargin,不设置shadowAffectRadius,此时会自动计算出在这么多的空间内,最大能绘制的模糊半径
 * [useCompatPadding]: 是否考虑前景的圆角,添加对应的padding,避免子布局覆盖圆角
 */
fun View.setShadow(useCompatPadding: Boolean = false, settingBlock: ShadowSetting.() -> Unit) {
    val setting = ShadowSetting().apply(settingBlock).apply {

        // 当没有设置shadowMargin等参数的时候,自动计算阴影需要的绘制区间
        if (shadowMarginLeft == null && shadowMargin == null) {
            shadowMarginLeft = calMargin(shadowAffectRadius, -shadowDx)
        }
        if (shadowMarginRight == null && shadowMargin == null) {
            shadowMarginRight = calMargin(shadowAffectRadius, shadowDx)
        }
        if (shadowMarginTop == null && shadowMargin == null) {
            shadowMarginTop = calMargin(shadowAffectRadius, -shadowDy)
        }
        if (shadowMarginBottom == null && shadowMargin == null) {
            shadowMarginBottom = calMargin(shadowAffectRadius, shadowDy)
        }
        var left = shadowMarginLeft ?: shadowMargin ?: 0
        var right = shadowMarginRight ?: shadowMargin ?: 0
        var top = shadowMarginTop ?: shadowMargin ?: 0
        var bottom = shadowMarginBottom ?: shadowMargin ?: 0

        // 如果阴影的模糊半径没有设置,自动计算出在这么多的空间内,最大能绘制的模糊半径
        if (shadowAffectRadius == 0f) {
            shadowAffectRadius = calRadius(left, right, top, bottom)
        }
        // ViewGroup需要设置一定的Padding,避免子布局绘制在阴影或者边框上
        if (this@setShadow is ViewGroup) {
            if (useCompatPadding) {
                val radiusTopLeft = shapeCornerRadiusTL ?: shapeCornerRadius ?: 0
                val radiusTopRight = shapeCornerRadiusTR ?: shapeCornerRadius ?: 0
                val radiusBottomLeft = shapeCornerRadiusBL ?: shapeCornerRadius ?: 0
                val radiusBottomRight = shapeCornerRadiusBR ?: shapeCornerRadius ?: 0
                left += radiusTopLeft.coerceAtLeast(radiusBottomLeft)
                right += radiusTopRight.coerceAtLeast(radiusBottomRight)
                top += radiusTopLeft.coerceAtLeast(radiusTopRight)
                bottom += radiusBottomLeft.coerceAtLeast(radiusBottomRight)
            }
            setPadding(left, top, right, bottom)
        }
    }

    val shadowDrawable = ShadowDrawable(setting)
    ViewCompat.setBackground(this, shadowDrawable)
}

private fun ShadowSetting.calRadius(left: Int, right: Int, top: Int, bottom: Int): Float {
    return minOf(
        left + shadowDx,
        right - shadowDx,
        top + shadowDy,
        bottom - shadowDy
    ) * 3 / 4
}

private fun calMargin(radius: Float, diff: Float): Int {
    return 0f.coerceAtLeast(radius + (radius / 3) + diff).toInt()
}